import BaseModal from '@/components/base/BaseModal';
import useUserStore from '@/store/user';
import Axios, { AxiosRequestConfig, Method } from 'axios';
import { stringify } from 'qs';
import { isProd } from '../is';
import { CreateRequestConfig, Request, RequestConfig, ResponseResult, Result } from './type';

Axios.defaults.paramsSerializer = (params: any) => {
  return stringify(params, { arrayFormat: 'repeat', allowDots: true });
};

/**
 * 创建 请求 实例的方法，返回一个请求实例
 * @param {object} config 实例配置
 * @returns 请求 实例
 */
function createRequest(config: CreateRequestConfig) {
  const { requestInterceptor, successInterceptor, errorInterceptor, ...axiosConfig } = config;
  const axiosInstance = Axios.create({
    timeout: 10000,
    headers: {
      'Content-Type': 'application/json;charset=UTF-8'
    },
    ...axiosConfig
  });
  axiosInstance.interceptors.request.use(
    (reqConfig) => {
      if (requestInterceptor) {
        reqConfig = requestInterceptor(reqConfig);
      }
      const { token } = useUserStore.getState();
      if (token) {
        // 判断token是否存在
        reqConfig.headers.PHMToken = `${token}`; // 将token设置成请求头
      }
      const url = reqConfig.url as string;
      reqConfig.url = url.replace(/[\u200B-\u200D\uFEFF]/g, '');
      return reqConfig;
    },
    (err) => {
      return Promise.reject(err);
    }
  );
  const request: Request = async <T>(
    url: string,
    method: Method,
    data?: unknown,
    options?: RequestConfig<T>
  ): Result<T> => {
    const opt = { error: true, loading: true, ...options } as RequestConfig<unknown>;
    let res = {} as ResponseResult<unknown>;
    const { confirm, onConfirm } = opt;
    // 是否需要请求前验证
    let confirmResult = true;
    if (confirm) {
      const { type = 'error', content } = confirm;
      confirmResult = await new Promise<boolean>((reslove) => {
        const onOk = () => reslove(true);
        const onCancel = () => reslove(false);
        BaseModal.confirm({
          type,
          content,
          onOk,
          onCancel
        });
      });
      onConfirm && onConfirm(confirmResult);
      if (confirmResult === false) {
        res.ok = false;
        res.err = { message: 'confirm 取消', name: 'user' };
      }
    }
    if (confirmResult === true) {
      try {
        const hasParams = ['get', 'delete'].includes(method);
        const response = await axiosInstance({
          url,
          method,
          data: !hasParams ? data : null,
          params: hasParams ? data : null,
          ...opt
        });
        res = successInterceptor
          ? successInterceptor(res, response, opt)
          : { data: response.data, ok: true, err: null };
      } catch (resError: any) {
        // 服务器级别错误
        const error = resError.toJSON();
        if (!isProd) {
          console.log(error);
        }
        if (errorInterceptor) {
          res = errorInterceptor(res, resError, opt);
        } else {
          res.ok = false;
          res.err = { name: 'system', message: error.message ?? '请求错误' };
        }
      }
    }
    return res as ResponseResult<T>;
  };

  request.get = <T>(url: string, data?: unknown, opt?: AxiosRequestConfig): Result<T> => {
    return request<T>(url, 'get', data, opt);
  };
  request.list = (url: string, data?: unknown, opt?: AxiosRequestConfig) => {
    return request(url, 'get', data, opt);
  };

  request.post = <T>(url: string, data?: unknown, opt?: AxiosRequestConfig): Result<T> => {
    return request<T>(url, 'post', data, opt);
  };
  request.put = <T>(url: string, data?: unknown, opt?: AxiosRequestConfig): Result<T> => {
    return request<T>(url, 'put', data, opt);
  };
  request.delete = <T>(url: string, data?: unknown, opt?: AxiosRequestConfig): Result<T> => {
    return request<T>(url, 'delete', data, opt);
  };
  request.patch = <T>(url: string, data?: unknown, opt?: AxiosRequestConfig): Result<T> => {
    return request<T>(url, 'patch', data, opt);
  };
  return request;
}

export default createRequest;
